<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>PL/0编译器</title>
</head>

<body>
  <script src="../js/vue.js"></script>
  <script src="../element-ui/lib/index.js"></script>
  <link rel="stylesheet" href="../element-ui/lib/theme-chalk/index.css">
  <script src="../js/axios-0.18.0.js"></script>

  <div id="app">
    <el-container>
      <el-col :span="3">
        <div>&nbsp;</div>
      </el-col>
      <el-aside width="210px">
        <el-menu default-active="1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
          background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" :default-openeds="['1', '2']">
          <el-submenu index="1">
            <template slot="title">
              <i class="el-icon-folder"></i>
              <span>常规测试用例</span>
            </template>
            <el-menu-item-group>
              <el-menu-item index="1-1" @click="setCode1">自增减、复合运算</el-menu-item>
              <el-menu-item index="1-2" @click="setCode2">！、%、sqrt()</el-menu-item>
              <el-menu-item index="1-3" @click="setCode3">if then else</el-menu-item>
              <el-menu-item index="1-4" @click="setCode4">for</el-menu-item>
              <el-menu-item index="1-5" @click="setCode5">repeat</el-menu-item>
              <el-menu-item index="1-6" @click="setCode6">一维数组</el-menu-item>
              <el-menu-item index="1-7" @click="setCode7">function</el-menu-item>
              <el-menu-item index="1-8" @click="setCode8">sample0</el-menu-item>
              <el-menu-item index="1-9" @click="setCode9">sample1</el-menu-item>
              <el-menu-item index="1-10" @click="setCode10">sample2</el-menu-item>
              <el-menu-item index="1-11" @click="setCode11">sample3</el-menu-item>
              <el-menu-item index="1-12" @click="setCode12">SumOfn!</el-menu-item>
              <el-menu-item index="1-13" @click="setCode13">test_recursive</el-menu-item>
            </el-menu-item-group>
          </el-submenu>
          <el-submenu index="2">
            <template slot="title">
              <i class="el-icon-folder-opened"></i>
              <span>其他测试用例</span>
            </template>
            <el-menu-item-group>
              <el-menu-item index="1-1">选项1</el-menu-item>
              <el-menu-item index="1-2">选项2</el-menu-item>
              <el-menu-item index="1-3">选项3</el-menu-item>
              <el-menu-item index="1-4">选项4</el-menu-item>
            </el-menu-item-group>
          </el-submenu>
        </el-menu>
      </el-aside>
      <el-container>
        <el-header>
          <el-row>
            <el-col :span="20">
              <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"
                background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
                <el-menu-item index="1" @click="click1"> 个 人 中 心 </el-menu-item>
                <el-menu-item index="2" @click="click2"> 词 法 分 析 </el-menu-item>
                <el-menu-item index="3" @click="click3"> 完 整 功 能 </el-menu-item>
              </el-menu>
            </el-col>
          </el-row>
        </el-header>
        <el-main>
          <el-row>
            <el-col :span="1">
              <div>&nbsp;</div>
            </el-col>
            <el-col :span="8">
              <el-input type="textarea" :rows="26" placeholder="请输入PL/0代码" v-model="textarea1"></el-input>
            </el-col>
            <el-col :span="1">
              <div>&nbsp;</div>
            </el-col>
            <el-col :span="9">
              <el-input type="textarea" :rows="15" placeholder="代码分析区" v-model="textarea2" :disabled="false"></el-input>
              <br><br>
              <el-input type="textarea" :rows="9" placeholder="结果输出区" v-model="textarea3" :disabled="false"></el-input>
            </el-col>
          </el-row>

          <el-row>
            <el-col>&nbsp;</el-col>
          </el-row>

          <el-row>
            <el-col :span="3">
              <div>&nbsp;</div>
            </el-col>
            <el-col :span="11">
              <el-upload class="upload-demo" action="" :on-preview="handlePreview" :on-remove="handleRemove"
                :before-remove="beforeRemove" multiple :limit="3" :on-exceed="handleExceed" :file-list="fileList"
                :on-change="uploadTxt">
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <el-button size="small" type="primary">点击上传</el-button>
              </el-upload>
            </el-col>
            <el-col :span="4">
              <el-button size="small" type="success" @click="analyze">编译并解释执行</el-button>
            </el-col>
          </el-row>
        </el-main>
      </el-container>
    </el-container>


    <el-row>
      <el-col>&nbsp;</el-col>
    </el-row>


  </div>

  <script>
    new Vue({
      el: "#app",

      mounted() {
        this.getAccount();
      },

      methods: {
        getAccount() {
          let url = location.search; //获取url中"?"符后的字串
          if (url.indexOf("?") != -1) {    //判断是否有参数
            // 从第一个字符开始 因为第0个是?号 获取所有除问号的所有符串
            let str = url.substr(1).split("=");   //用等号进行分隔
            this.pl0_code.account = str[1];
          }
          else {
            this.$message.error("错误！非法访问");
            location.replace("http://localhost:8080/home.html");
          }
        },
        analyze() {
          this.pl0_code.code = this.textarea1;
          let date = new Date();
          let year = date.getFullYear();        //年 ,从 Date 对象以四位数字返回年份
          let month = date.getMonth() + 1;      //月 ,从 Date 对象返回月份 (0 ~ 11) ,date.getMonth()比实际月份少 1 个月
          let day = date.getDate();             //日 ,从 Date 对象返回一个月中的某一天 (1 ~ 31)
          let hours = date.getHours();          //小时 ,返回 Date 对象的小时 (0 ~ 23)
          let minutes = date.getMinutes();      //分钟 ,返回 Date 对象的分钟 (0 ~ 59)
          let seconds = date.getSeconds();      //秒 ,返回 Date 对象的秒数 (0 ~ 59)
          //修改月份格式
          if (month >= 1 && month <= 9) {
            month = "0" + month;
          }
          //修改日期格式
          if (day >= 0 && day <= 9) {
            day = "0" + day;
          }
          //修改小时格式
          if (hours >= 0 && hours <= 9) {
            hours = "0" + hours;
          }
          //修改分钟格式
          if (minutes >= 0 && minutes <= 9) {
            minutes = "0" + minutes;
          }
          //修改秒格式
          if (seconds >= 0 && seconds <= 9) {
            seconds = "0" + seconds;
          }
          //获取当前系统时间  格式(yyyy-mm-dd hh:mm:ss)
          let currentFormatDate = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
          this.pl0_code.time = currentFormatDate;
          axios.post("http://localhost:8080/phrase", this.pl0_code).then(resp => {
            if (resp.data.code === 20011) {
              this.$message.success("分析成功！");
              this.instruction = resp.data.data;
              if(this.instruction[this.instruction.length - 1].f === "编译成功！") {
                this.textarea3 = "编译成功！\n";
                this.instruction.length -= 1;
                for (let i = 0; i < this.instruction.length; i++) {
                  this.textarea2 += i + 1 + "、" + this.instruction[i].f + " " + this.instruction[i].l + " " + this.instruction[i].a;
                  if (i != this.instruction.length - 1) this.textarea2 += "\n";
                }
                this.interpret();
              }
              else {
                this.textarea3 = this.instruction[this.instruction.length - 1].f + "\n";
              }
            }
            else if (resp.data.code === 20010) {
              this.$message.error("分析失败！");
            }
            else {
              this.$message.error("服务器请求超时！");
            }
          });
        },
        interpret() {
          let p = 0, b = 0, t = 0;						// 指令指针，指令基址，栈顶指针
          let s = new Array(500);		// 栈
          s[0] = s[1] = s[2] = 0;
          do {
            let i = this.instruction[p];	// 读当前指令
            p++; // p指向要执行的下一条指令
            switch (i.f) {
              case "LIT":				// 将a的值取到栈顶
                s[t] = parseInt(i.a);
                t++;
                break;
              case "OPR":				// 数学、逻辑运算
                switch (parseInt(i.a)) {
                  case 0: // 结束并调用过程，返回调用点并退栈
                    t = b;
                    p = s[t + 2]; // 下一条指令的地址
                    b = s[t + 1]; // 上层程序的指令基址
                    break;
                  case 1: // 栈顶元素的相反数，栈顶指针指向栈顶的上一个元素
                    s[t - 1] = -1 * s[t - 1];
                    break;
                  case 2:
                    t--;
                    s[t - 1] = s[t - 1] + s[t];
                    break;
                  case 3:
                    t--;
                    s[t - 1] = s[t - 1] - s[t];
                    break;
                  case 4:
                    t--;
                    s[t - 1] = s[t - 1] * s[t];
                    break;
                  case 5:
                    t--;
                    s[t - 1] = s[t - 1] / s[t];
                    break;
                  case 6: //#栈顶元素为奇数则变为1，为偶数则变为0
                    s[t - 1] = s[t - 1] % 2;
                    break;
                  case 8:
                    t--;
                    s[t - 1] = (s[t - 1] == s[t] ? 1 : 0);
                    break;
                  case 9:
                    t--;
                    s[t - 1] = (s[t - 1] != s[t] ? 1 : 0);
                    break;
                  case 10:
                    t--;
                    s[t - 1] = (s[t - 1] < s[t] ? 1 : 0);
                    break;
                  case 11:
                    t--;
                    s[t - 1] = (s[t - 1] >= s[t] ? 1 : 0);
                    break;
                  case 12:
                    t--;
                    s[t - 1] = (s[t - 1] > s[t] ? 1 : 0);
                    break;
                  case 13:
                    t--;
                    s[t - 1] = (s[t - 1] <= s[t] ? 1 : 0);
                    break;
                  case 14: // 栈顶元素输出
                    this.textarea3 += "输出：" + s[t - 1];
                    t--;
                    break;
                  case 15:
                    this.textarea3 += "\n";
                    break;
                  case 16:
                    s[t] = 0;
                    let value = window.prompt("PL/0程序需要一个输入", "");
                    s[t] = parseInt(value);
                    this.textarea3 += "输入：" + s[t] + "\n";
                    t++;
                    break;
                  case 17:
                    s[t - 1] = parseInt(Math.sqrt(s[t - 1]));
                    break;
                  case 18:
                    t--;
                    s[t - 1] = s[t] / s[t - 1];
                    break;
                  case 19:
                    t--;
                    s[t - 1] = s[t - 1] % s[t];
                    break;
                  case 20: /*新增加，取反操作符，栈顶元素为零，则置为1，否则置为0*/
                    if (s[t - 1] == 0) {
                      s[t - 1] = 1;
                    }
                    else {
                      s[t - 1] = 0;
                    }
                    break;
                }
                break;
              case "LOD":				// 取相对当前过程的数据基地址为a的内存的值到栈顶
                s[t] = s[this.base(parseInt(i.l), s, b) + parseInt(i.a)]; //#首先根据层次差l找到声明变量的过程的基地址，再将a作为偏移地址取值
                t++;
                break;
              case "LODA":  // 当前次栈顶存放的是数组内的相对索引，栈顶存放的是表达式的值，需要将数组中的元素放到栈顶
                s[t] = s[this.base(parseInt(i.l), s, b) + parseInt(i.a) + s[t - 2]];
                t++;
                break;
              case "LODA2": // 此时只是使用数组的值，当前栈顶元素为数组的相对索引，将数组的值放到相对索引处，栈顶指针不变
                s[t - 1] = s[this.base(parseInt(i.l), s, b) + parseInt(i.a) + s[t - 1]];
                break;
              case "STO":				// 栈顶的值存到相对当前过程的数据基地址为a的内存
                t--;
                s[this.base(parseInt(i.l), s, b) + parseInt(i.a)] = s[t];
                break;
              case "STOA":  // 当前次栈顶存放的是array的相对索引，栈顶存放的是要存在数组中的数
                t--;
                s[this.base(parseInt(i.l), s, b) + parseInt(i.a) + s[t - 1]] = s[t];  // i.a中存放的是数组的首地址的相对偏移量
                t--; // 再退一个，将数组中的相对索引退掉
                break
              case "CAL":				// 调用子过程
                s[t] = this.base(parseInt(i.l), s, b); 	// 将静态作用域基地址入栈
                s[t + 1] = b;					// 将动态作用域基地址入栈
                s[t + 2] = p;					// 将当前指令指针入栈
                b = t;  					// 改变基地址指针值为新过程的基地址
                p = parseInt(i.a);   					// 跳转
                break;
              case "INT":			// 分配内存
                t += parseInt(i.a);
                break;
              case "JMP":				// 直接跳转
                p = parseInt(i.a);
                break;
              case "JPC":				// 条件跳转（当栈顶为0的时候跳转）
                t--;
                if (s[t] == 0)
                  p = parseInt(i.a);
                break;
              case "CPY":  // 新增，将栈顶下第a个元素复制到栈顶
                s[t] = s[t - 1 - parseInt(i.a)];
                t++;
                break;
              case "RPM": // 新增，用于处理数组的后置加加，当前栈顶为数组中元素的值，次栈顶为1或-1，
                // 将次栈顶元素与栈顶元素相加存入数组中，并将相加前的数组的值放到索引位置
                // 指令格式为RPM l a 其中a为item.adr，l为层差
                s[this.base(parseInt(i.l), s, b) + parseInt(i.a) + s[t - 3]] = s[t - 1] + s[t - 2];
                s[t - 3] = s[t - 1]; // 将数组原来的值存放在相对索引的位置
                t -= 2; // 退两个元素
                break;
              case "MOVE": // 新增，用于移动栈顶指针，MOVE 0 a，a表示相对移动的位置，上移为正，下为负
                t += parseInt(i.a);
                break;
            }
          } while (p != 0);
        },
        // getValue() {
        //   this.$prompt('PL/0程序需要一个输入', '提示', {
        //   confirmButtonText: '确定',
        //   cancelButtonText: '取消'
        // }).then(({ value }) => {
        //   return value;
        // });
        // },
        base(l, s, b) {
          let b1 = b;
          while (l > 0) {
            b1 = s[b1];
            l--;
          }
          return b1;
        },
        uploadTxt(file, fileList) {
          this.textarea1 = "";
          this.textarea2 = "";
          this.textarea3 = "";
          let reader = new FileReader();
          reader.readAsText(file.raw);
          reader.onload = () => {
            this.textarea1 = reader.result;
          };
        },
        setCode1() {
          this.textarea1 =
                  "var a, b;\n" +
                  "\n" +
                  "procedure init;\n" +
                  "  begin\n" +
                  "    a := 1;\n" +
                  "    b := 2;\n" +
                  "  end;\n" +
                  "procedure print;\n" +
                  "  begin\n" +
                  "    write(a);\n" +
                  "    write(b);\n" +
                  "  end;\n" +
                  "\n" +
                  "begin\n" +
                  "  call init;\n" +
                  "  ++a;       \n" +
                  "  call print; {a=2,b=2}\n" +
                  "\n" +
                  "  call init;\n" +
                  "  a += 1;\n" +
                  "  call print; {a=2,b=2}\n" +
                  "\n" +
                  "  call init;\n" +
                  "  a := ++b;\n" +
                  "  call print; {a=3,b=3}\n" +
                  "\n" +
                  "  call init;\n" +
                  "  a += b++; {用b自增之前的值}\n" +
                  "  call print; {a=3,b=3}\n" +
                  "\n" +
                  "  call init;\n" +
                  "  a := ++b * a--; {3*1}\n" +
                  "  call print; {a=3,b=3}\n" +
                  "  \n" +
                  "  call init;\n" +
                  "  a := -++b * --a; {-3*0}\n" +
                  "  call print; {a=0,b=3}\n" +
                  "\n" +
                  "  call init;\n" +
                  "  a := -(++b) * (--a);\n" +
                  "  call print; {a=0,b=3}\n" +
                  "end.\n";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode2() {
          this.textarea1 =
                  "var c_c; {标识符中带有下划线}\n" +
                  "begin\n" +
                  "    c_c := 9;\n" +
                  "    write(!c_c);     {0}\n" +
                  "    write(c_c%2);    {1}\n" +
                  "    write(sqrt(c_c)) {3}\n" +
                  "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode3() {
          this.textarea1 =
                  "var c;\n" +
                  "\n" +
                  "begin\n" +
                  "    c := 5;\n" +
                  "    if c = 5 then\n" +
                  "      c := 10\n" +
                  "    else\n" +
                  "      c := 15;\n" +
                  "    write(c)\n" +
                  "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode4() {
          this.textarea1 =
                  "var i;\n" +
                  "begin\n" +
                  "  for i:=1 to 10 do\n" +
                  "  write(i);\n" +
                  "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode5() {
          this.textarea1 =
                  "var i;\n" +
                  "begin \n" +
                  "  i := 0;\n" +
                  "  repeat\n" +
                  "  begin\n" +
                  "    write(i);\n" +
                  "    ++i;\n" +
                  "  end\n" +
                  "  until i>10\n" +
                  "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode6() {
          this.textarea1 =
                  "var\n" +
                  "a(1:5),b;\n" +
                  "\n" +
                  "  begin\n" +
                  "    a(1) := 3;\n" +
                  "    a(2) := 2;\n" +
                  "    b := a(1);\n" +
                  "    write(b);      {3}\n" +
                  "    \n" +
                  "    write(a(1)++); {3，a(1)值为4}\n" +
                  "    write(a(1));   {4}\n" +
                  "    a(1) := - ++a(2) * 2; {3*2在取相反数}\n" +
                  "    write(a(1))    {-6}\n" +
                  "  end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode7() {
          this.textarea1 =
                  "var x, y;\n" +
                  "\n" +
                  "procedure function;\n" +
                  "if x < 1 then\n" +
                  "    y := x\n" +
                  "else\n" +
                  "    if x < 10 then\n" +
                  "        y := 2 * x - 1\n" +
                  "    else\n" +
                  "        y := 3 * x - 11\n" +
                  ";\n" +
                  "begin\n" +
                  "    read(x);\n" +
                  "    call function;\n" +
                  "    write(y)\n" +
                  "end.";
        },
        setCode8() {
          this.textarea1 =
            "const a=10; var result;\n"
            + "procedure average;\n"
            + "var temp, addition, count;\n"
            + "\n"
            + "procedure add;\n"
            + "  begin\n"
            + "     temp:=temp+2;\n"
            + "     write(temp);\n"
            + "  end;\n"
            + "\n"
            + "begin\n"
            + "    temp:=a;\n"
            + "    count:=1;\n"
            + "    addition:=temp;\n"
            + "    while temp<=20 do\n"
            + "       begin\n"
            + "           call add;\n"
            + "           count:=count+1;\n"
            + "           addition:=addition+temp;\n"
            + "       end;\n"
            + "    result:=addition/count;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "   write(a);\n"
            + "   call average;\n"
            + "   write(result);\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode9() {
          this.textarea1 =
            "const true=1, false=0;\n"
            + "var i, j, k;\n"
            + "procedure recttri;\n"
            + "\n"
            + "var temp1, temp2, temp3;\n"
            + "    begin\n"
            + "         write ( i );\n"
            + "         write (j);\n"
            + "         write(k);\n"
            + "         temp2:=j*j;\n"
            + "         temp3:=k*k;\n"
            + "         while temp1+temp2 #temp3 do\n"
            + "                begin\n"
            + "                     write(false);\n"
            + "                      i:=i+1;\n"
            + "\t\t      temp1:=i*i;\n"
            + "                end;\n"
            + "                write(true);\n"
            + "        end;\n"
            + "\n"
            + "begin\n"
            + "i:=3;\n"
            + "j:=8;\n"
            + "k:=10;\n"
            + "call recttri;\n"
            + "write(i);\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode10() {
          this.textarea1 =
            "const pi=3;\n"
            + "var c, flag;\n"
            + "procedure compare;\n"
            + "var area1, area2;\n"
            + "procedure rad;\n"
            + "var r1, r2;\n"
            + "\n"
            + "begin\n"
            + "r1:=c/(2*pi);\n"
            + "r2:=c/4;\n"
            + "area1:=pi*r1*r1;\n"
            + "area2:=r2*r2;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "call rad;\n"
            + "if area1<area2 then\n"
            + "begin\n"
            + "write (area2);\n"
            + "flag:=2;\n"
            + "end;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "flag:=1;\n"
            + "c:=16;\n"
            + "call compare;\n"
            + "write(flag);\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode11() {
          this.textarea1 =
            "const bound=30;\n"
            + "var input, count;\n"
            + "procedure guess;\n"
            + "var temp, upper, lower;\n"
            + "procedure locate;\n"
            + "\n"
            + "begin\n"
            + "temp:=(upper+lower)/2;\n"
            + "if temp<input then\n"
            + "lower:=temp+1;\n"
            + "if temp>input then\n"
            + "upper:=temp-1;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "upper:=bound;\n"
            + "lower:=0;\n"
            + "temp:=(upper+lower)/2;\n"
            + "while temp#input do\n"
            + "begin\n"
            + "count:=count+1;\n"
            + "call locate;\n"
            + "end;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "input:=6;\n"
            + "count:=1;\n"
            + "call guess;\n"
            + "write(count);\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode12() {
          this.textarea1 =
            "var n, m, fact, sum;\n"
            + "\n"
            + "procedure factorial;\n"
            + "begin\n"
            + "    if m > 0 then\n"
            + "        begin\n"
            + "            fact := fact * m;\n"
            + "            m := m - 1;\n"
            + "            call factorial\n"
            + "        end;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "    read(n);\n"
            + "    sum := 0;\n"
            + "    while n > 0 do\n"
            + "        begin\n"
            + "            m := n;\n"
            + "            fact := 1;\n"
            + "            call factorial;\n"
            + "            sum  := sum + fact;\n"
            + "            n := n - 1\n"
            + "        end;\n"
            + "    write(sum)\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        setCode13() {
          this.textarea1 =
            "var n;\n"
            + "\n"
            + "procedure rec;\n"
            + "begin\n"
            + "    if n # 0 then\n"
            + "        begin\n"
            + "            write(n);\n"
            + "            n := n - 1;\n"
            + "            call rec\n"
            + "        end;\n"
            + "end;\n"
            + "\n"
            + "begin\n"
            + "    read(n);\n"
            + "    call rec\n"
            + "end.";
          this.textarea2 = "";
          this.textarea3 = "";
        },
        click1() {
          location.replace("http://localhost:8080/user.html?account=" + this.pl0_code.account);
        },
        click2() {
          location.replace("http://localhost:8080/word.html?account=" + this.pl0_code.account);
        },
        click3() {
          location.replace("http://localhost:8080/phrase.html?account=" + this.pl0_code.account)
        },
        handleSelect(key, keyPath) { },
        handleRemove(file, fileList) { },
        handlePreview(file) { },
        handleExceed(files, fileList) {
          this.$message.error(`只能上传一个文件`);
        },
        beforeRemove(file, fileList) {
          return this.$confirm("确定移除 ${ file.name }？");
        }
      },

      data() {
        return {
          textarea1: "",
          textarea2: "",
          textarea3: "",
          activeIndex: "3",
          fileList: [],
          pl0_code: {
            id: "",
            account: "",
            code: "",
            time: ""
          },
          instruction: []
        }
      }
    })
  </script>
</body>

</html>